<?php

namespace CtyunOss\api;

use AlexTartan\Array2Xml\ArrayToXml;
use AlexTartan\Array2Xml\XmlToArray;
use CtyunOss\config\OssConfig;
use CtyunOss\config\Request;
use CtyunOss\cors\OssHttp;
use CtyunOss\exceptions\OssUploadException;
use CtyunOss\struct\ListBucketResult;
use Symfony\Component\Mime\MimeTypes;
use Symfony\Component\VarDumper\VarDumper;

/**
 * Class OssBucket
 * @package CtyunOss\api
 *
 * @author  Violet_Ice紫冰 <violetice@aliyun.com>
 * @create  2020-06-26 21:23:14
 */
class OssBucket
{
    /** @var OssConfig 天翼云OSS配置 */
    private $config;

    public function __construct(OssConfig $config)
    {
        $this->config = $config;
    }

    /**
     * 查询文件对象列表
     *
     * @param string $prefix
     * @param int $max
     * @param string $next
     *
     * @return ListBucketResult
     * @throws \AlexTartan\Array2Xml\Exception\ConversionException
     * @throws \CtyunOss\exceptions\OssConfigException
     * @throws \CtyunOss\exceptions\OssHttpException
     * @throws \CtyunOss\exceptions\OssSignException
     * @throws \Symfony\Contracts\HttpClient\Exception\HttpExceptionInterface
     * @throws \Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface
     */
    public function getObjects(string $prefix = '', int $max = 1000, string $next = '')
    {
        $prefix = ltrim($prefix, '/');
        $config = $this->config;
        OssConfig::isBucket($config);

        $request = new Request();
        $request->setBucket($config->getBucket());
        $request->setHost($config->getEndpoint());
        $request->setUrl('/');

        $request->setQuery('prefix', $prefix);
        $request->setQuery('max-keys', $max);
        $request->setQuery('marker', $next);

        $http = new OssHttp($request, $config);
        $res  = $http->send();
        $data = (new XmlToArray())->buildArrayFromString($res);
        if ($this->config->debug) {
            VarDumper::dump('XML Array: ');
            VarDumper::dump($data);
        }
        return new ListBucketResult($data['ListBucketResult']);
    }

    /**
     * 上传单个文件
     *
     * @param string $objectName
     * @param \SplFileInfo $file
     * @param bool $redundancy
     *
     * @return bool
     * @throws OssUploadException
     * @throws \AlexTartan\Array2Xml\Exception\ConversionException
     * @throws \CtyunOss\exceptions\OssConfigException
     * @throws \CtyunOss\exceptions\OssHttpException
     * @throws \CtyunOss\exceptions\OssSignException
     * @throws \Symfony\Contracts\HttpClient\Exception\HttpExceptionInterface
     * @throws \Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface
     */
    public function putObject(string $objectName, \SplFileInfo $file, bool $redundancy = true)
    {
        $config = $this->config;
        OssConfig::isBucket($config);

        $regex = '/^\/([\w\d-]+)(\/[\w\d-]+)*(\.[\w\d]+)?$/';
        if (!preg_match($regex, $objectName)) {
            throw new OssUploadException('$objectName 不正确，请适配正则(' . $regex . ')');
        }

        if (!$file->isFile()) {
            throw new OssUploadException($file->getPathname() . ' 这不是文件');
        }

        $request = new Request();
        $request->setMethod('PUT');
        $request->setBucket($config->getBucket());
        $request->setHost($config->getEndpoint());
        $request->setUrl($objectName);
        $request->setHeader([
            'Content-Length' => $file->getSize(),
            'Content-Type'   => (new MimeTypes())->getMimeTypes($file->getExtension())[0],
            'Content-MD5'    => base64_encode(md5_file($file->getRealPath(), true))
        ]);
        $request->setXHeader('x-amz-storage-class', $redundancy ? 'STANDARD' : 'REDUCED_REDUNDANCY');
        $request->setOptions([
            'body' => fopen($file->getRealPath(), 'r')
        ]);

        $http = new OssHttp($request, $config);
        $res  = $http->send();
        if ($res === '') {
            return true;
        }
        return false;
    }

    /**
     * 删除单个文件
     *
     * @param string $objectName
     *
     * @return bool
     * @throws OssUploadException
     * @throws \AlexTartan\Array2Xml\Exception\ConversionException
     * @throws \CtyunOss\exceptions\OssConfigException
     * @throws \CtyunOss\exceptions\OssHttpException
     * @throws \CtyunOss\exceptions\OssSignException
     * @throws \Symfony\Contracts\HttpClient\Exception\HttpExceptionInterface
     * @throws \Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface
     */
    public function delObject(string $objectName)
    {
        $config = $this->config;
        OssConfig::isBucket($config);

        $regex = '/^\/([\w\d-]+)(\/[\w\d-]+)*(\.[\w\d]+)?$/';
        if (!preg_match($regex, $objectName)) {
            throw new OssUploadException('$objectName 不正确，请适配正则(' . $regex . ')');
        }

        $request = new Request();
        $request->setMethod('DELETE');
        $request->setBucket($config->getBucket());
        $request->setHost($config->getEndpoint());
        $request->setUrl($objectName);

        $http = new OssHttp($request, $config);
        $res  = $http->send();
        if ($res === '') {
            return true;
        }
        return false;
    }

    /*public function delObjects(array $objectNames)
    {
        $config = $this->config;
        OssConfig::isBucket($config);

        $regex = '/^\/([\w\d-]+)(\/[\w\d-]+)*(\.[\w\d]+)?$/';

        foreach ($objectNames as $k => $objectName) {
            if (!preg_match($regex, $objectName)) {
                throw new OssUploadException('$objectNames[' . $k . '] 不正确，请适配正则(' . $regex . ')');
            }
        }

        $request = new Request();
        $request->setMethod('POST');
        $request->setBucket($config->getBucket());
        $request->setHost($config->getEndpoint());
        $request->setUrl('/');
        $request->setQuery('delete', '');

        $data = [];
        foreach ($objectNames as $objectName) {
            $data['Object'][] = ['Key' => ltrim($objectName, '/')];
        }

        $xml = (new ArrayToXml())->buildXml(['Delete' => $data])->saveXML();
        $xml = explode("\n", $xml)[1];
        $len = mb_strlen($xml);

        $request->setHeader([
            'Content-Length' => $len,
            'Content-MD5'    => base64_encode(md5($xml, true))
        ]);
        $request->setOptions([
            'body'    => $xml,
            'headers' => [
                'Content-Type' => (new MimeTypes())->getMimeTypes('xml')[0],
            ]
        ]);

        $http = new OssHttp($request, $config);
        $res  = $http->send(true);
        return $res;
    }*/
}